package grex;

/**
 * <p>Title: </p> <p>Description: </p> <p>Copyright: Copyright (c) 2003</p>
 * <p>Company: </p>
 *
 * @author not attributable
 * @version 1.0
 */
import grex.IO.ConsoleOutputHandler;
import grex.ErrorManagement.ErrorHandlerConsole;
import grex.ErrorManagement.ErrorManager;
import grex.Data.ArffTableModel;
import grex.Graphics.GREXGUI;
import grex.Nodes.GeneException;

import java.io.IOException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.StringTokenizer;
import javax.swing.SwingUtilities;

public class World {

    private Population population;
    private Environment environment;
    private GP bestEver, bestValidationEver;

    public World(int poulationSize, String bnfFile, String dataFile) throws BNFException, GeneException, IOException {
        environment = new Environment(dataFile, bnfFile);

        population = new Population(poulationSize, environment);
    }

    public World() throws BNFException, GeneException, IOException {
    }

    public Environment getEnvironment() {
        return environment;
    }

    public GP getBestValidationEverGP() {
        return bestValidationEver;
    }

    public GP getBestEverGP() {
        return bestEver;
    }

    public GP selectBestGP() {
        return population.selectBestInPopulation();
    }

    public void createNewPopulation(Environment environment) throws BNFException, GeneException, IOException {
        this.environment = environment;
        this.environment.initProblemType();
        population = new Population(environment.getOptions().getPOPULATION_SIZE(), environment);
        bestEver = population.getBestGP();
        bestValidationEver = bestEver;
    }

    public void createNewPopulation(GP[] gps, Environment environment) throws
            BNFException, GeneException, IOException {
        this.environment = environment;
        population = new Population(gps, environment);
        bestEver = population.getBestGP();
        bestValidationEver = bestEver;
    }

    public void createNewPopulation(int populationSize, GP gp, Environment environment) throws
            BNFException, GeneException, IOException {
        this.environment = environment;
        population = new Population(populationSize, gp, environment);
        bestEver = population.getBestGP();
        bestValidationEver = bestEver;
    }
    //OBS environment moste skapas innan forhand! GPet anvonds for som mall for populationen

    public void createNewPopulation(int populationSize, GP gp) throws
            BNFException, GeneException, IOException {
        population = new Population(populationSize, gp, environment);
        bestEver = population.getBestGP();
        bestValidationEver = bestEver;
    }

    public void evolve(int generations) throws GeneException, BNFException {
        bestEver.calcAdjustedFitness();
        for (int i = 0; i < generations; i++) {
            population.evolvePopulation();
            if (population.getBestGP().getFitness() < bestEver.getFitness()) {
                bestEver = population.getBestGP();
            }
        }
    }

    public double getAvgPopulationFitness() {
        return population.getAvgPopulationFitness();
    }

    public double getAvgPopulationLength() {
        return population.getPopulationLength();
    }
//Returner det verkliga vordet och det predicerade vordet i en strong avgronsad med \n

    public String bestTestPrediction() throws GeneException {
        GP best = population.getBestGP();
        String tmp = best.getGPTestPrediction();
        return tmp;
    }
    //returnerar predictionen for tesmongden i en arraylist

    public ArrayList getBestTestPredictionAsArrayList() throws GeneException {
        GP best = population.getBestGP();
        return best.getGPTestPredictionAsArrayList();
    }

    public Population getPopulation() {
        return population;
    }

    public static double parseDouble(String s) {
        NumberFormat nf = NumberFormat.getInstance(new Locale("sv", "se"));
        double d = Double.MAX_VALUE;
        try {
            return Double.parseDouble(s.trim());
        } catch (Exception ex) {
            try {
                return nf.parse(s.trim()).doubleValue();
            } catch (Exception ex2) {
                System.out.println("unable to parse: " + s + " to double");
                return -999999999;
            }
        }
    }

    private static void initWeights(String s) {
        /*
         * StringTokenizer st = new StringTokenizer(s,";\"");
         * Settings.WEIGHTS=new double[st.countTokens()]; for(int i
         * =0;st.hasMoreTokens();i++){
         * Settings.WEIGHTS[i]=parseDouble(st.nextToken());
    }
         */
    }

    public static void main(String[] args) throws IOException, BNFException, GeneException {
//    showSplashScreen();
     /*
         * WekaTreeReader wtr = new WekaTreeReader(); wtr.loadFile();
     System.exit(0);
         */
        Long startTime = System.currentTimeMillis();
        Options.rnd = new java.util.Random(startTime);
        //Options.rnd=new java.util.Random(1);
        ErrorManager.getInstance().addErrorhandler(new ErrorHandlerConsole());


        if (true && args != null && args.length > 0) {
            ConsoleOutputHandler coh = new ConsoleOutputHandler();

            StringTokenizer s;
            String cs = "";
            Options options = new Options();
            for (int i = 0; i < args.length; i++) {
                s = new StringTokenizer(args[i], "= ");
                cs = s.nextToken();
                if (cs.equalsIgnoreCase("bnf")) {
                    options.setBNF_FILE(s.nextToken());
                } else if (cs.equalsIgnoreCase("fil")) {
                    options.setDATA_FILE(s.nextToken());
                } else if (cs.equalsIgnoreCase("tra")) {
                    options.setTRAIN_SIZE(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("tes")) {
                    options.setTEST_SIZE(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("val")) {
                    options.setVAL_SIZE(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("gen")) {
                    options.setGENERATIONS(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("pop")) {
                    options.setPOPULATION_SIZE(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("cro")) {
                    options.setCROSSOVER_PROBABILITY(Double.parseDouble(s.nextToken()));
                } else if (cs.equalsIgnoreCase("mut")) {
                    options.setMUTATION_PROBABILITY(Double.parseDouble(s.nextToken()));
                } else if (cs.equalsIgnoreCase("crd")) {
                    options.setMAX_CREATION_DEPTH(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("len")) {
                    options.setPUNISHMENT_FOR_LENGTH(Double.parseDouble(s.nextToken()));
                } else if (cs.equalsIgnoreCase("trc")) {
                    options.setTRAIN_IMPORTENS(Double.parseDouble(s.nextToken()));
                } else if (cs.equalsIgnoreCase("vac")) {
                    options.setVAL_IMPORTENS(Double.parseDouble(s.nextToken()));
                } else if (cs.equalsIgnoreCase("nro")) {
                    options.setNR_OFF_CATEGORIAL_ITEMS(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("bat")) {
                    options.setBATCH_SIZE(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("mof")) {
                    options.setMOFFN_USED(s.nextToken().equalsIgnoreCase("TRUE"));
                } else if (cs.equalsIgnoreCase("sim")) {
                    options.setSIMPLIFICATION(s.nextToken().equalsIgnoreCase("TRUE"));
                } else if (cs.equalsIgnoreCase("lff")) {
                    options.setLENGTH_FACTOR_OLD(s.nextToken().equalsIgnoreCase("TRUE"));
                } else if (cs.equalsIgnoreCase("crt")) {
                    options.setCREATION_TYPE(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("eli")) {
                    options.setELITISM(s.nextToken().equalsIgnoreCase("TRUE"));
                } else if (cs.equalsIgnoreCase("per")) {
                    options.setSTOP_WITHOUT_IMPROVMENT(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("tom")) {
                    options.setTOMBOLA(s.nextToken().equalsIgnoreCase("TRUE"));
                } else if (cs.equalsIgnoreCase("tpr")) {
                    options.setTOMBOLA_PERCENT(Double.parseDouble(s.nextToken()));
                } else if (cs.equalsIgnoreCase("tsl")) {
                    options.setTOMBOLA_SLOTS(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("tin")) {
                    options.setTOMBOLA_INTERVALL(Integer.parseInt(s.nextToken()));
                } else if (cs.equalsIgnoreCase("tfi")) {
                    options.setTOMBOLA_FITNESFUNTCION(s.nextToken());
                } else if (cs.equalsIgnoreCase("wei")) {
                    throw new BNFException("Weights are not implemented yet, fix needed i world!");//initWeights(s.nextToken());
                } else {
                    throw new BNFException(cs + "does_not_exist");
                }
            }
            EvolutionProcess evolution = new EvolutionProcess(new ArffTableModel(options.getDATA_FILE()), options);
            evolution.addEvolutionListener(coh);
            evolution.addSimplificationListener(coh);

            if (args.length == 2) {
                evolution.startEvolution(options.getDATA_FILE(), options.getBNF_FILE());
            } else {
                evolution.startEvolution();
            }
        } else {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    GREXGUI gui = new GREXGUI();
                    gui.setVisible(true);
                }
            });

            //GUI g = new GUI(world1,false);
            //g.setVisible(true);
        }
        //*/
    }
}
